iT邦幫忙

2022 iThome 鐵人賽

DAY 26
1
Web 3

從以太坊白皮書理解 web 3 概念系列 第 27

從以太坊白皮書理解 web 3 概念 - Day26

  • 分享至 

  • xImage
  •  

從以太坊白皮書理解 web 3 概念 - Day26

NFT School Day 4 - Mint with NFT.storage and Polygon

今天將會透過 mint-nftstorege-polygon 來學習如何透過透過 nft.storage service 在 Polygon 鏈上鑄造 NFT

鑄造方案解說

為了以下3個特性

  1. 可拓展性: 也就是鑄造所需要的花費不能太高且鑄造速度不能太慢
  2. 持久性: 也就是 asset 資料必須能夠一直在 NFT BURN 之前都存在
  3. 不可修改性: 也就是 NFT 與其對應的數位資產需要避免被惡意串改

所以選用了 Polygon 鏈與 nft.storage 這個 IPFS servcie

Polygon 鏈強調於其可拓展性。並且相容於 Ethereum 與 EVM。

nft.storage 則保證其持久性透過 Filecoin 網路,透過 IPFS 保證其不可修改性

鑄造環境設定

為了能夠方便測試與運行 Smart Contract

需要先安裝 nodejs 到 16.14.0 與 npm 需要在版本 8.0.0 以上

其他設定

  1. 安裝 MetaMask 錢包
  2. 設定 MetaMask 連接網路到 Polygon Mumbai 測試鏈
  3. 透過 Mumbai faucet 取得 MATIC token
  4. 複製 MetaMask 錢包製作出來 Private Key: 需要這個來產生簽章

準備

取得 nft.storage 的 API KEY

透過 nft.storage 網址 登入

並且透過設定產生一把 API KEY

這把 API KEY 是用來使用 storage api 所需要的

設定 node module 執行環境

  • Hardhat 與 Hardhat-Ethers 還有 ethers: 這是用來開發 Ethereum 的開發執行環境其中相容於 Polygon
  • OpenZeppelin: 用來開發 Smart Contract 的函式庫
  • nft.storage: 用來連接 nft.storage api
  • dotenv: 用來讀取環境變數

建立資料夾 polygon_nft_mint

mkdir polygon_nft_mint

初始化 node_module 環境

yarn init -y

安裝所需套件

yarn add hardhat @openzeppelin/contracts nft.storage dotenv @nomiclabs/hardhat-ethers ethers@^5.0.0

執行 hardhat 初始化

npx hardhat

選擇 Create an empty hardhat.config.js

✔ What do you want to do? · Create an empty hardhat.config.js
✨ Config file created ✨

然後更新 hardhat.config.js 如下

/**
* @type import('hardhat/config').HardhatUserConfig
*/
require("@nomiclabs/hardhat-ethers");
require('dotenv').config();
const { PRIVATE_KEY } = process.env;
module.exports = {
  defaultNetwork: "PolygonMumbai",
  networks: {
    hardhat: {
    },
     PolygonMumbai: {
      url: "https://rpc-mumbai.maticvigil.com",
      accounts: [PRIVATE_KEY]
    }
  },
  solidity: {
    version: "0.8.12",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
}

建立一個 .env 檔案 內容如下

PRIVATE_KEY="wallet private key"
NFT_STORAGE_API_KEY="Your api key"

接下來分別建立3個資料

  1. contracts: 用來存放 Smart Contract
  2. assets: 用來存放要放到 nft.storage 的數位資料
  3. scripts: 用來存放要執行發佈的 javascript 檔案

建立指令如下:

mkdir contracts assets scripts

鑄造 NFT

把數位資產放到 nft.storage

建立一個 scripts/store-asset.mjs 內容如下

import { NFTStorage, File } from "nft.storage"
import fs from 'fs'
import dotenv from 'dotenv'
dotenv.config()

const API_KEY = process.env.NFT_STORAGE_API_KEY

async function storeAsset() {
   const client = new NFTStorage({ token: API_KEY })
   const metadata = await client.store({
       name: 'ShadowWarriorNFT',
       description: 'shadow warrior is an awesome artwork!',
       image: new File(
           [await fs.promises.readFile('assets/shadow.png')],
           'shadow.png',
           { type: 'image/png' }
       ),
   })
   console.log("Metadata stored on Filecoin and IPFS with URL:", metadata.url)
}

storeAsset()
   .then(() => process.exit(0))
   .catch((error) => {
       console.error(error);
       process.exit(1);
   });

透過執行以下指令就可以把數位資產上傳並且產生 meta 資料

node scripts/store-asset.mjs

在 Polygon 建立 NFT

建立 Smart Contract 來做鑄造

建立 contracts/ExampleNFT.sol 如下

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract ExampleNFT is ERC721URIStorage, Ownable {
   using Counters for Counters.Counter;
   Counters.Counter private _tokenIds;

   constructor() ERC721("NFT", "ENFT") {}

   function mintNFT(address recipient, string memory tokenURI)
       public onlyOwner
       returns (uint256)
   {
       _tokenIds.increment();

       uint256 newItemId = _tokenIds.current();
       _mint(recipient, newItemId);
       _setTokenURI(newItemId, tokenURI);

       return newItemId;
   }
}

在最上面引用了 4 個 Contract

@openzeppelin/contracts/token/ERC721/ERC721.sol 包含了所有 ERC-721 標準實作了關於 NFT Token 所需要的特性

@openzeppelin/contracts/utils/Counters.sol 替供了一個 Counter 類似於資料庫 Serial 一樣可以做到隨則呼叫 increment() 來不斷做增加,這邊用來當作 unqiue ID

@openzeppelin/contracts/access/Ownable.sol 用來設定 NFT 的存取權限

constructor 這邊用來把 ERC-721 特性附加到 NFT 上面

可以看到 mintNFT 這個 function 的存取權限是 onlyOwner 代表只有 Smart Contract 的 onwer 才能呼叫

mintNFT 的第一個參數 recipient 是用來設定 NFT 接收者的 address
mintNFT 的第二個參數 tokenURI 則是用來儲存一個能夠顯示 NFT metadata 的 URL

發佈 Smart Contract 到 Polygon 鏈

建立 scripts/deploy-contract.mjs 如下

async function deployContract() {
 const ExampleNFT = await ethers.getContractFactory("ExampleNFT")
 const exampleNFT = await ExampleNFT.deploy()
 await exampleNFT.deployed()
 // This solves the bug in Mumbai network where the contract address is not the real one
 const txHash = exampleNFT.deployTransaction.hash
 const txReceipt = await ethers.provider.waitForTransaction(txHash)
 const contractAddress = txReceipt.contractAddress
 console.log("Contract deployed to address:", contractAddress)
}

deployContract()
 .then(() => process.exit(0))
 .catch((error) => {
   console.error(error);
   process.exit(1);
 });

使用以下指令做發佈

npx hardhat run scripts/deploy-contract.mjs --network PolygonMumbai

鑄造 NFT 到 Polygon

接著利用剛剛的那兩個資訊

來撰寫 scripts/mint-nft.mjs

const CONTRACT_ADDRESS = "0x12b8FE2671325258c251C926918B162D2c822b46"
const META_DATA_URL = "ipfs://bafyreihqlqporf35mkbjul6453hqsocbqstb4uawql5laebjjybxhfflhe/metadata.json"

async function mintNFT(contractAddress, metaDataURL) {
   const ExampleNFT = await ethers.getContractFactory("ExampleNFT")
   const [owner] = await ethers.getSigners()
   await ExampleNFT.attach(contractAddress).mintNFT(owner.address, metaDataURL)
   console.log("NFT minted to: ", owner.address)
}

mintNFT(CONTRACT_ADDRESS, META_DATA_URL)
   .then(() => process.exit(0))
   .catch((error) => {
       console.error(error);
       process.exit(1);
   });

透過以下指令做鑄造

npx hardhat run scripts/mint-nft.mjs --network PolygonMumbai

然後就可以透過 openset 平台來察看已鑄造的 NFT

比如本文所鑄造NFT 如下

https://testnets.opensea.io/assets/mumbai/0x12b8fe2671325258c251c926918b162d2c822b46/1


上一篇
從以太坊白皮書理解 web 3 概念 - Day25
下一篇
從以太坊白皮書理解 web 3 概念 - Day27
系列文
從以太坊白皮書理解 web 3 概念32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言